PHP 递归函数的应用(三) 层级结构数据的树状输出

还是以应用一的数组为例

1
2
3
4
5
6
7
8
9
10
11
12
$data = array(
0 => array('id' => '1', 'pid' => 0, 'name' => '一级栏目一'),
1 => array('id' => '2', 'pid' => 1, 'name' => '二级栏目一'),
2 => array('id' => '3', 'pid' => 1, 'name' => '二级栏目二'),
3 => array('id' => '4', 'pid' => 2, 'name' => '三级栏目一'),
4 => array('id' => '5', 'pid' => 2, 'name' => '三级栏目二'),
5 => array('id' => '6', 'pid' => 3, 'name' => '三级栏目三'),
6 => array('id' => '7', 'pid' => 3, 'name' => '三级栏目四'),
7 => array('id' => '8', 'pid' => 0, 'name' => '一级栏目二'),
8 => array('id' => '9', 'pid' => 8, 'name' => '二级栏目三'),
9 => array('id' => '10', 'pid' => 7, 'name' => '四级栏目一'),
);

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
一级栏目一

├─ 二级栏目一

│ ├─ 三级栏目一

│ └─ 三级栏目二

└─ 二级栏目二

├─ 三级栏目三

└─ 三级栏目四

└─ 四级栏目一

一级栏目二

└─ 二级栏目三

还能以select形式展现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
class Tree
{
var $arr = array();
var $icon = array(
'│',
'├─',
'└─'
);
var $ret;

public function tree($arr = array())
{
$this->arr = $arr;
return is_array($arr);
}

function get_child($myid)
{
$newarr = array();
if (is_array($this->arr)) {
foreach ($this->arr as $id => $a) {
if ($a['pid'] == $myid) {
$newarr[$id] = $a;
}
}
}
return $newarr ? $newarr : false;
}

//获取带格式数组
function getArray($myid = 0, $sid = 0, $adds = '')
{
$number = 1;
$child = $this->get_child($myid);
if (is_array($child)) {
$total = count($child);
foreach ($child as $a) {
$j = $k = '';
if ($number == $total) {
$j .= $this->icon[2];
} else {
$j .= $this->icon[1];
$k = $adds ? $this->icon[0] : '';
}
$spacer = $adds ? $adds . $j : '';
$a['name'] = $spacer . ' ' . $a['name'];
$this->ret[] = $a;
$fd = $adds . $k . '    ';
$this->getArray($a['id'], $sid, $fd);
$number++;
}
}
return $this->ret;
}

//select
function get_tree($myid, $str, $sid = 0, $adds = '')
{
$number = 1;
$child = $this->get_child($myid);
if (is_array($child)) {
$total = count($child);
foreach ($child as $a) {
$id = $a['id'];
$j = $k = '';
if ($number == $total) {
$j .= $this->icon [2];
} else {
$j .= $this->icon [1];
$k = $adds ? $this->icon [0] : '';
}
$spacer = $adds ? $adds . $j : '';
$select = $id == $sid ? 'selected' : '';

$this->ret .= sprintf($str, $id, $select, $spacer, $a['name']);
$this->get_tree($id, $str, $sid, $adds . $k . ' ');
$number++;
}
}
return $this->ret;
}

//文件夹目录
function read_all_dir($dir, $onlyDir = true)
{
$result = array();
$handle = opendir($dir);
if ($handle) {
while (($file = readdir($handle)) !== false) {
if ($file != '.' && $file != '..') {
$cur_path = $dir . DIRECTORY_SEPARATOR . $file;
if (is_dir($cur_path)) {
$result[$file] = $this->read_all_dir($cur_path, $onlyDir);
} else {
if (!$onlyDir) {
$result[] = $file;
}
}
}
}
closedir($handle);
}
return $result;
}


//数组转换
function arrshift($array, $pid = 0)
{
static $r = [];
static $index = 1;
if (is_array($array) && count($array) > 0) {
foreach ($array as $k => $v) {
$r[] = array(
'id' => $index,
'pid' => $pid,
'name' => is_array($v) ? $k : $v
);
$index++;
$this->arrshift($v, $index - 1);
}
}
return $r;
}
}

得出数组用foreach循环即可输出树形结构

1
2
3
4
5
6
7
8
$tree = new Tree ();
$tree->tree($data);
$result = $tree->getArray();
foreach ($data as $value) {
echo $value['name'];
echo '<br/>';
echo '<br/>';
}

这里给出option模板

1
2
3
4
$html = '<select name="tree">';
$str = "<option value=%s %s>%s%s</option>";
$html .= $tree->get_tree(0, $str, 2) . '</select>';
echo $html;

即可输出select

1
get_tree($myid, $str, $sid = 0, $adds = '')

这里是$sid参数是给出slected的option的id

利用应用一的数组无限极分类和还原以及应用二的文件夹目录的遍历
可以树状结构输出文件夹目录

1
2
3
4
5
6
7
8
9
10
11
12
$tree = new Tree (); // new 之前请记得包含tree文件!
//文件夹遍历
$data = $tree->read_all_dir('/web/mall/Application/lib', false);
//转换成[['id','pid','name']]的二维数组
$data = $tree->arrshift($data);
$tree->tree($data);
$data = $tree->getArray();
foreach ($data as $value) {
echo $value['name'];
echo '<br/>';
echo '<br/>';
}

可以得到我们想要的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Action

├─ Admin

│ ├─ GoodAction.class.php

│ ├─ IndexAction.class.php

│ ├─ LoginAction.class.php

│ ├─ MenuAction.class.php

│ ├─ OrderAction.class.php

│ ├─ PublicAction.class.php

│ ├─ UserAction.class.php

│ ├─ UtilAction.class.php

│ ├─ WechatAction.class.php

│ └─ WeixinAction.class.php

├─ Api

│ └─ ApiAction.class.php

└─ App

├─ IndexAction.class.php

└─ Sms.class.php

log.txt

Model

├─ Admin

│ └─ OrderModel.class.php

└─ App

└─ OrderModel.class.php

虽然递归函数的效率和性能欠佳,但是对我们的逻辑训练还是有很大帮助的,我们可以写出一个方法并不断的优化和简单化,来提高我们的逻辑